package cn.gov.mwr.sl651;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;


import cn.gov.mwr.sl651.appendix.FD4;
import org.apache.commons.lang3.StringUtils;

import cn.gov.mwr.sl651.appendix.FC;
import cn.gov.mwr.sl651.command.UpCommand;
import cn.gov.mwr.sl651.AbstractBody;
import cn.gov.mwr.sl651.HydroBuilder;
import cn.gov.mwr.sl651.HydroMessage;
import cn.gov.mwr.sl651.IMessage;
import cn.gov.mwr.sl651.IMessageBody;
import cn.gov.mwr.sl651.IMessageHeader;
import cn.gov.mwr.sl651.Symbol;
import cn.gov.mwr.sl651.header.AscHeader;
import cn.gov.mwr.sl651.header.HexHeader;
import cn.gov.mwr.sl651.utils.ByteUtil;
import cn.gov.mwr.sl651.utils.CRC16Helper;

/**
 * 命令类，针对下发指令时所使用此类进行组装消息
 *
 * @author admin
 */
public class Command {

    private Map<String, FC> FcHexMap = new Hashtable<String, FC>();
    private Map<String, FD4> Fd4HexMap = new Hashtable<String, FD4>();
    protected byte startBit = Symbol.SOH_HEX;
    protected byte[] centerAddr;
    protected byte[] stationAddr;
    protected byte[] password;
    protected byte[] funcCode;// 这个不能只用字节
    protected byte upDown;
    protected byte bodyStartBit;
    protected byte[] bodyCount;
    protected byte eof;

    private Command() {
        initFC();
        initFD4();
    }

    public Command(byte upDown) {
        this();
        this.upDown = upDown;
    }

    private void initFD4() {
        Fd4HexMap.put( "20", new FD4( 20, "20", "PJ", "定时报时间间隔", "", 1, 0 ) );
        Fd4HexMap.put( "21", new FD4( 21, "21", "PJ", "加报时间间隔", "", 1, 0 ) );
        Fd4HexMap.put( "22", new FD4( 22, "22", "PJ", "降水量日起始时间", "", 1, 0 ) );
        Fd4HexMap.put( "23", new FD4( 22, "23", "PJ", "采样间隔", "", 2, 0 ) );
        Fd4HexMap.put( "27", new FD4( 28, "27", "PJ", "雨量加报阈值", "", 1, 0 ) );
        Fd4HexMap.put( "28", new FD4( 28, "28", "PJ", "水位基值 1", "", 4, 3 ) );
        Fd4HexMap.put( "30", new FD4( 30, "30", "PJ", "加报水位", "", 3, 3 ) );
        Fd4HexMap.put( "38", new FD4( 38, "38", "PJ", "水位修正基值", "", 2, 2 ) );
        Fd4HexMap.put( "40", new FD4( 40, "40", "PJ", "加报水位以上加报阈值", "", 2, 2 ) );
        Fd4HexMap.put( "41", new FD4( 41, "41", "PJ", "加报水位以下加报阈值", "", 2, 2 ) );
    }

    private void initFC() {
        FcHexMap.put( "F0", new FC( 1, "F0", "TT", "观测时间引导符", "　", 10, 0 ) );
        FcHexMap.put( "F1", new FC( 2, "F1", "ST", "测站编码引导符", "　", 10, 0 ) );
        FcHexMap.put( "F2", new FC( 3, "F2", "RGZS", "人工置数", "d字节", 0, 0 ) );
        FcHexMap.put( "F3", new FC( 4, "F3", "PIC", "图片信息", "KB", 0, 0 ) );
        FcHexMap.put( "F4", new FC( 5, "F4", "DRP", "1小时内每5分钟时段雨量。", "0.1毫米", 12,
                0 ) );
        FcHexMap.put( "F5", new FC( 6, "F5", "DRZ1", "1小时内5分钟间隔相对水位1", "0.01米",
                24, 0 ) );
        FcHexMap.put( "F6", new FC( 7, "F6", "DRZ2", "1小时内5分钟间隔相对水位2", "0.01米",
                24, 0 ) );
        FcHexMap.put( "F7", new FC( 8, "F7", "DRZ3", "1小时内5分钟间隔相对水位3", "0.01米",
                24, 0 ) );
        FcHexMap.put( "F8", new FC( 9, "F8", "DRZ4", "1小时内5分钟间隔相对水位4", "0.01米",
                24, 0 ) );
        FcHexMap.put( "F9", new FC( 10, "F9", "DRZ5", "1小时内5分钟间隔相对水位5", "0.01米",
                24, 0 ) );
        FcHexMap.put( "FA", new FC( 11, "FA", "DRZ6", "1小时内5分钟间隔相对水位6", "0.01米",
                24, 0 ) );
        FcHexMap.put( "FB", new FC( 12, "FB", "DRZ7", "1小时内5分钟间隔相对水位7", "0.01米",
                24, 0 ) );
        FcHexMap.put( "FC", new FC( 13, "FC", "DRZ8", "1小时内5分钟间隔相对水位8", "0.01米",
                24, 0 ) );
        FcHexMap.put( "FD", new FC( 14, "FD", "DATA", "流速批量数据传输", "", 0, 0 ) );
        FcHexMap.put( "01", new FC( 15, "01", "AC", "断面面积", "平方米", 5, 2 ) );
        FcHexMap.put( "02", new FC( 16, "02", "AI", "瞬时气温", "摄氏度", 2, 1 ) );
        FcHexMap.put( "03", new FC( 17, "03", "C", "瞬时水温", "摄氏度", 2, 1 ) );
        FcHexMap.put( "04", new FC( 18, "04", "DRxnn", "时间步长码", "　", 3, 0 ) );
        FcHexMap.put( "05", new FC( 19, "05", "DT", "时段长,降水、引排水、抽水历时", "小时.分钟",
                2, 0 ) );
        FcHexMap.put( "06", new FC( 20, "06", "ED", "日蒸发量", "毫米", 3, 1 ) );
        FcHexMap.put( "07", new FC( 21, "07", "EJ", "当前蒸发", "毫米", 3, 1 ) );
        FcHexMap.put( "08", new FC( 22, "08", "FL", "气压", "百帕", 5, 0 ) );
        FcHexMap.put( "09", new FC( 23, "09", "GH", "闸坝、水库闸门开启高度", "米", 4, 2 ) );
        FcHexMap.put( "0A", new FC( 24, "0A", "GN", "输水设备、闸门(组)编号", "　", 3, 0 ) );
        FcHexMap.put( "0B", new FC( 25, "0B", "GS", "输水设备类别", "　", 1, 0 ) );
        FcHexMap.put( "0C", new FC( 26, "0C", "GT", "水库、闸坝闸门开启孔数", "孔", 3, 0 ) );
        FcHexMap.put( "0D", new FC( 27, "0D", "GTP", "地温", "摄氏度", 2, 1 ) );
        FcHexMap.put( "0E", new FC( 28, "0E", "H", "地下水瞬时埋深", "米", 4, 2 ) );
        FcHexMap.put( "0F", new FC( 29, "0F", "HW", "波浪高度", "米", 4, 2 ) );
        FcHexMap.put( "10", new FC( 30, "10", "M10", "10厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "11", new FC( 31, "11", "M20", "20厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "12", new FC( 32, "12", "M30", "30厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "13", new FC( 33, "13", "M40", "40厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "14", new FC( 34, "14", "M50", "50厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "15", new FC( 35, "15", "M60", "60厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "16", new FC( 36, "16", "M80", "80厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "17", new FC( 37, "17", "M100", "100厘米处土壤含水量", "百分比", 3, 1 ) );
        FcHexMap.put( "18", new FC( 38, "18", "MST", "湿度", "百分比", 3, 1 ) );
        FcHexMap.put( "19", new FC( 39, "19", "NS", "开机台数", "台", 2, 0 ) );
        FcHexMap.put( "1A", new FC( 40, "1A", "P1", "1小时时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "1B", new FC( 41, "1B", "P2", "2小时时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "1C", new FC( 42, "1C", "P3", "3小时时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "1D", new FC( 43, "1D", "P6", "6小时时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "1E", new FC( 44, "1E", "P12", "12小时时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "1F", new FC( 45, "1F", "PD", "日降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "20", new FC( 46, "20", "PJ", "当前降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "21", new FC( 47, "21", "PN01", "1分钟时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "22", new FC( 48, "22", "PN05", "5分钟时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "23", new FC( 49, "23", "PN10", "10分钟时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "24", new FC( 50, "24", "PN30", "30分钟时段降水量", "毫米", 3, 1 ) );
        FcHexMap.put( "25", new FC( 51, "25", "PR", "暴雨量", "毫米", 3, 1 ) );
        FcHexMap.put( "26", new FC( 52, "26", "PT", "降水量累计值", "毫米", 4, 1 ) );
        FcHexMap.put( "27", new FC( 53, "27", "Q", "瞬时流量、抽水流量", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "28", new FC( 54, "28", "Q1", "取(排）水口流量1", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "29", new FC( 55, "29", "Q2", "取(排）水口流量2", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2A", new FC( 56, "2A", "Q3", "取(排）水口流量3", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2B", new FC( 57, "2B", "Q4", "取(排）水口流量4", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2C", new FC( 58, "2C", "Q5", "取(排）水口流量5", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2D", new FC( 59, "2D", "Q6", "取(排）水口流量6", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2E", new FC( 60, "2E", "Q7", "取(排）水口流量7", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "2F", new FC( 61, "2F", "Q8", "取(排）水口流量8", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "30", new FC( 62, "30", "QA", "总出库流量、过闸总流量", "立方米/秒", 6, 3 ) );
        FcHexMap.put( "31", new FC( 63, "31", "QZ", "输水设备流量、过闸(组)流量", "立方米/秒", 6,
                3 ) );
        FcHexMap.put( "32", new FC( 64, "32", "SW", "输沙量", "万吨", 7, 3 ) );
        FcHexMap.put( "33", new FC( 65, "33", "UC", "风向", "　", 2, 0 ) );
        FcHexMap.put( "34", new FC( 66, "34", "UE", "风力(级)", "　", 2, 0 ) );
        FcHexMap.put( "35", new FC( 67, "35", "US", "风速", "米/秒", 3, 1 ) );
        FcHexMap.put( "36", new FC( 68, "36", "VA", "断面平均流速", "米/秒", 4, 3 ) );
        FcHexMap.put( "37", new FC( 69, "37", "VJ", "当前瞬时流速", "米/秒", 4, 3 ) );
        FcHexMap.put( "38", new FC( 70, "38", "VT", "电源电压", "伏特", 3, 2 ) );
        FcHexMap.put( "39", new FC( 71, "39", "Z", "瞬时河道水位、潮位", "米", 5, 3 ) );
        FcHexMap.put( "3A", new FC( 72, "3A", "ZB", "库(闸、站)下水位", "米", 5, 3 ) );
        FcHexMap.put( "3B", new FC( 73, "3B", "ZU", "库(闸、站)上水位", "米", 5, 3 ) );
        FcHexMap.put( "3C", new FC( 74, "3C", "Z1", "取(排）水口水位1 ", "米", 5, 3 ) );
        FcHexMap.put( "3D", new FC( 75, "3D", "Z2", "取(排）水口水位2 ", "米", 5, 3 ) );
        FcHexMap.put( "3E", new FC( 76, "3E", "Z3", "取(排）水口水位3 ", "米", 5, 3 ) );
        FcHexMap.put( "3F", new FC( 77, "3F", "Z4", "取(排）水口水位4 ", "米", 5, 3 ) );
        FcHexMap.put( "40", new FC( 78, "40", "Z5", "取(排）水口水位5 ", "米", 5, 3 ) );
        FcHexMap.put( "41", new FC( 79, "41", "Z6", "取(排）水口水位6 ", "米", 5, 3 ) );
        FcHexMap.put( "42", new FC( 80, "42", "Z7", "取(排）水口水位7 ", "米", 5, 3 ) );
        FcHexMap.put( "43", new FC( 81, "43", "Z8", "取(排）水口水位8 ", "米", 5, 3 ) );
        FcHexMap.put( "44", new FC( 82, "44", "SQ", "含沙量", "千克/立方米", 6, 3 ) );
        FcHexMap.put( "45", new FC( 83, "45", "ZT", "遥测站状态及报警信息（定义见表58）", "　", 4,
                0 ) );
        FcHexMap.put( "46", new FC( 84, "46", "pH", "pH值", "　", 3, 2 ) );
        FcHexMap.put( "47", new FC( 85, "47", "DO", "溶解氧", "毫克/升", 3, 1 ) );
        FcHexMap.put( "48", new FC( 86, "48", "COND", "电导率", "微西门/厘米 ", 5, 0 ) );
        FcHexMap.put( "49", new FC( 87, "49", "TURB", "浊度", "度", 3, 0 ) );
        FcHexMap.put( "4A", new FC( 88, "4A", "CODMN", "高锰酸盐指数", "毫克/升", 3, 1 ) );
        FcHexMap.put( "4B", new FC( 89, "4B", "REDOX", "氧化还原电位", "毫伏", 3, 1 ) );
        FcHexMap.put( "4C", new FC( 90, "4C", "NH4N", "氨氮", "毫克/升", 4, 2 ) );
        FcHexMap.put( "4D", new FC( 91, "4D", "TP", "总磷", "毫克/升", 4, 3 ) );
        FcHexMap.put( "4E", new FC( 92, "4E", "TN", "总氮", "毫克/升", 4, 2 ) );
        FcHexMap.put( "4F", new FC( 93, "4F", "TOC", "总有机碳", "毫克/升", 3, 2 ) );
        FcHexMap.put( "50", new FC( 94, "50", "CU", "铜", "毫克/升", 6, 4 ) );
        FcHexMap.put( "51", new FC( 95, "51", "ZN", "锌", "毫克/升", 5, 4 ) );
        FcHexMap.put( "52", new FC( 96, "52", "SE", "硒", "毫克/升", 6, 5 ) );
        FcHexMap.put( "53", new FC( 97, "53", "AS", "砷", "毫克/升", 6, 5 ) );
        FcHexMap.put( "54", new FC( 98, "54", "THG", "总汞", "毫克/升", 6, 5 ) );
        FcHexMap.put( "55", new FC( 99, "55", "CD", "镉", "毫克/升", 6, 5 ) );
        FcHexMap.put( "56", new FC( 100, "56", "PB", "铅", "毫克/升", 6, 5 ) );
        FcHexMap.put( "57", new FC( 101, "57", "CHLA", "叶绿素a", "毫克/升", 3, 2 ) );
        FcHexMap.put( "58", new FC( 102, "58", "WP1", "水压1", "千帕", 4, 2 ) );
        FcHexMap.put( "59", new FC( 103, "59", "WP2", "水压2", "千帕", 4, 2 ) );
        FcHexMap.put( "5A", new FC( 104, "5A", "WP3", "水压3", "千帕", 4, 2 ) );
        FcHexMap.put( "5B", new FC( 105, "5B", "WP4", "水压4", "千帕", 4, 2 ) );
        FcHexMap.put( "5C", new FC( 106, "5C", "WP5", "水压5", "千帕", 4, 2 ) );
        FcHexMap.put( "5D", new FC( 107, "5D", "WP6", "水压6", "千帕", 4, 2 ) );
        FcHexMap.put( "5E", new FC( 108, "5E", "WP7", "水压7", "千帕", 4, 2 ) );
        FcHexMap.put( "5F", new FC( 109, "5F", "WP8", "水压8", "千帕", 4, 2 ) );
        FcHexMap.put( "60", new FC( 110, "60", "SYL1", "水表1剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "61", new FC( 111, "61", "SYL2", "水表2剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "62", new FC( 112, "62", "SYL3", "水表3剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "63", new FC( 113, "63", "SYL4", "水表4剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "64", new FC( 114, "64", "SYL5", "水表5剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "65", new FC( 115, "65", "SYL6", "水表6剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "66", new FC( 116, "66", "SYL7", "水表7剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "67", new FC( 117, "67", "SYL8", "水表8剩余水量", "立方米", 7, 3 ) );
        FcHexMap.put( "68",
                new FC( 118, "68", "SBL1", "水表1每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "69",
                new FC( 119, "69", "SBL2", "水表2每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6A",
                new FC( 120, "6A", "SBL3", "水表3每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6B",
                new FC( 121, "6B", "SBL4", "水表4每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6C",
                new FC( 122, "6C", "SBL5", "水表5每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6D",
                new FC( 123, "6D", "SBL6", "水表6每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6E",
                new FC( 124, "6E", "SBL7", "水表7每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "6F",
                new FC( 125, "6F", "SBL8", "水表8每小时水量", "立方米/小时", 6, 2 ) );
        FcHexMap.put( "70", new FC( 126, "70", "VTA", "交流A相电压", "伏特", 3, 1 ) );
        FcHexMap.put( "71", new FC( 127, "71", "VTB", "交流B相电压", "伏特", 3, 1 ) );
        FcHexMap.put( "72", new FC( 128, "72", "VTC", "交流C相电压", "伏特", 3, 1 ) );
        FcHexMap.put( "73", new FC( 129, "73", "VIA", "交流A相电流", "安培", 3, 1 ) );
        FcHexMap.put( "74", new FC( 130, "74", "VIB", "交流B相电流", "安培", 3, 1 ) );
        FcHexMap.put( "75", new FC( 131, "75", "VIC", "交流C相电流", "安培", 3, 1 ) );
        FcHexMap.put( "FF", new FC( 132, "FF", "FFC", "信号强度", "信号强度", 1, 0 ) );
        FcHexMap.put( "FD", new FC( 133, "FD", "FDC", "流速", "流速", 24, 0 ) );
    }

    public FC getFcHex(String hex) {
        FC fc = FcHexMap.get( hex );
        if (fc == null) {
            fc = new FC();
            fc.setHex( hex );
            fc.setLen( 0 );
            fc.setDecimal( 0 );
        }
        return fc;
    }

    public FD4 getFd4Hex(String hex) {
        FD4 fd4 = Fd4HexMap.get( hex );
        if (fd4 == null) {
            fd4 = new FD4();
            fd4.setHex( hex );

            fd4.setLen( 0 );
            fd4.setDecimal( 0 );
        }
        return fd4;
    }

    public byte[] getBodyCount() {
        return bodyCount;
    }

    public void setBodyCount(byte[] bodyCount) {
        this.bodyCount = bodyCount;
    }

    public byte getStartBit() {
        return startBit;
    }

    public void setStartBit(byte startBit) {
        this.startBit = startBit;
    }

    public byte getUpDown() {
        return upDown;
    }

    public void setUpDown(byte upDown) {
        this.upDown = upDown;
    }

    public byte[] getFuncCode() {
        return funcCode;
    }

    public void setFuncCode(byte[] funcCode) {
        this.funcCode = funcCode;
    }

    public byte getBodyStartBit() {
        return bodyStartBit;
    }

    public void setBodyStartBit(byte bodyStartBit) {
        this.bodyStartBit = bodyStartBit;
    }

    public byte getEof() {
        return eof;
    }

    public void setEof(byte eof) {
        this.eof = eof;
    }

    public byte[] getCenterAddr() {
        return centerAddr;
    }

    public void setCenterAddr(byte[] centerAddr) {
        this.centerAddr = centerAddr;
    }

    public byte[] getStationAddr() {
        return stationAddr;
    }

    public void setStationAddr(byte[] stationAddr) {
        this.stationAddr = stationAddr;
    }

    public byte[] getPassword() {
        return password;
    }

    public void setPassword(byte[] password) {
        this.password = password;
    }

    /**
     * 初始化数据报文，只初始化序列值和时间
     *
     * @param sequence
     * @param date
     * @return
     */
    protected void initBase(AbstractBody body, int sequence, String date) {

        body.setSerialId( sequence );// 流水号 ，取值范围01 - 65535

        if (StringUtils.isBlank( date )) {
            SimpleDateFormat sdf = new SimpleDateFormat( "yyMMddHHmmss" );
            body.setSendDate( sdf.format( new Date() ) );
        } else {
            body.setSendDate( date );// 发报时间
        }
    }

    protected IMessageHeader buildHeader(IMessageBody body) {
        // 报文头
        IMessageHeader header;

        if (this.startBit == Symbol.SOH_ASC) {
            header = new AscHeader();
        } else {
            header = new HexHeader();
        }

        HydroBuilder.newStartBit( header );
        HydroBuilder.newCenterAddr( header, centerAddr ); // 1-255,按十六进制数输入,从配置文件中读取
        HydroBuilder.newStationAddr( header, this.stationAddr );// 从配置文件中读取
        HydroBuilder.newPassword( header, password );// 从配置文件中读取
        HydroBuilder.newFuncCode( header, this.funcCode );
        HydroBuilder.newBodyLength( header, this.upDown, body.getLength() );

        HydroBuilder.newBodyStartBit( header, new byte[]{this.bodyStartBit} );
        if (this.bodyStartBit == Symbol.SYN) {// 根据SYN来判断是否使用M3模式
            HydroBuilder.newBodyCount( header, this.bodyCount );
        }

        return header;
    }

    protected byte[] builderCrc(IMessage message) {

        StringBuffer sb = new StringBuffer();
        sb.append( toHexString( message.getHeader() ) );

        // msg = msg + ByteUtil.toHexString(message.getBody().getContent());

        if (message.getHeader().getStartBit()[0] == Symbol.SOH_ASC) {

            String hexstr = ByteUtil
                    .toHexString( message.getBody().getContent() ).toUpperCase();

            sb.append( ByteUtil.toHexString( hexstr.getBytes() ) );// 需要将ASC转换为HEX

        } else {
            sb.append( ByteUtil.toHexString( message.getBody().getContent() )
                    .toUpperCase() );
        }

        sb.append( ByteUtil.toHexString( message.getEOF() ) );

        String crc = CRC16Helper.crc16Check( sb.toString() );

        if (message.getHeader().getStartBitLen() == 2) {
            return ByteUtil.HexStringToBinary( crc );
        } else {
            return crc.getBytes();
        }

    }

    protected IMessage buildMessage(IMessageBody body) {

        try {
            HydroMessage message = new HydroMessage();
            message.setHeader( buildHeader( body ) );
            message.setBody( body );
            message.setEOF( this.eof );
            message.setCRC( builderCrc( message ) );

            return message;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 在这个方法中需要添加对ASC和HEX两种报文的转议
     *
     * @param header
     * @return
     */
    public String toHexString(IMessageHeader header) {
        StringBuffer sb = new StringBuffer( header.getLength() );
        sb.append( ByteUtil.toHexString( header.getStartBit() ) );
        if (header.getStartBitLen() == 2) {// HEX报文
            if (Symbol.UP == this.upDown) {
                sb.append( ByteUtil.toHexString( header.getCenterAddr() ) );
                sb.append( ByteUtil.toHexString( header.getStationAddr() ) );
            } else {
                sb.append( ByteUtil.toHexString( header.getStationAddr() ) );
                sb.append( ByteUtil.toHexString( header.getCenterAddr() ) );
            }
            sb.append( ByteUtil.toHexString( header.getPassword() ) );
            sb.append( ByteUtil.toHexString( header.getFuncCode() ) );
            sb.append( ByteUtil.toHexString( header.getBodySize() ) );
        } else {// ASC报文
            if (Symbol.UP == this.upDown) {
                sb.append( new String( header.getCenterAddr() ) );
                sb.append( new String( header.getStationAddr() ) );
            } else {
                sb.append( new String( header.getStationAddr() ) );
                sb.append( new String( header.getCenterAddr() ) );
            }
            sb.append( new String( header.getPassword() ) );
            sb.append( new String( header.getFuncCode() ) );
            sb.append( new String( header.getBodySize() ) );
        }
        sb.append( ByteUtil.toHexString( header.getBodyStartBit() ) );
        if (header.getBodyStartBit()[0] == Symbol.SYN) {
            sb.append( ByteUtil.toHexString( header.getBodyCount() ) );
        }
        return sb.toString();
    }

    public String printHexString(IMessage message) {
        StringBuffer sb = new StringBuffer();
        sb.append( toHexString( message.getHeader() ).toUpperCase() );
        if (message.getHeader().getStartBit()[0] == Symbol.SOH_ASC) {

            String hexstr = ByteUtil
                    .toHexString( message.getBody().getContent() ).toUpperCase();

            sb.append( ByteUtil.toHexString( hexstr.getBytes() ) );// 需要将ASC转换为HEX
        } else {
            sb.append( ByteUtil.toHexString( message.getBody().getContent() )
                    .toUpperCase() );
        }

        sb.append( ByteUtil.toHexString( message.getEOF() ).toUpperCase() );
        sb.append( ByteUtil.toHexString( message.getCRC() ).toUpperCase() );
        return sb.toString();
    }

    public static void main(String[] args) {
        UpCommand cmd = new UpCommand();
        cmd.setBodyStartBit( Symbol.STX );
        cmd.setEof( Symbol.ETX );
        cmd.setFuncCode( new byte[]{(byte) 0x2F} );

        IMessage message = cmd.send2FMessage( 1, null );

        System.out.println( ">> hex " + cmd.printHexString( message ) );

        String hexStr = cmd.toHexString( message.getHeader() );
        System.out.print( ">> hex " + hexStr.toUpperCase() );
        System.out.print( ""
                + ByteUtil.toHexString( message.getBody().getContent() ) );
        System.out.print( "" + ByteUtil.toHexString( message.getEOF() ) );
        System.out.print( "" + ByteUtil.toHexString( message.getCRC() ) );
    }

}
